﻿
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class PrefabLightmapData2 : MonoBehaviour
{
    [System.Serializable]
    struct RendererInfo
    {
        public Renderer renderer;
        public int lightmapIndex;
        public Vector4 lightmapScaleOffset;
    }
    [System.Serializable]
    struct TerrainRendererInfo
    {
        public Terrain terrain;
        public int lightmapIndex;
        public Vector4 lightmapScaleOffset;
    }

    [System.Serializable]
    struct LightmapInfo
    {
        public Texture2D lightmapFar;
        public Texture2D lightmapNear;
        public string FarName;
        public string NearName;
    }

    [SerializeField]
    RendererInfo[] m_RendererInfo;
    [SerializeField]
    LightmapInfo[] m_Lightmaps;
    [SerializeField]
    TerrainRendererInfo[] m_TerrainRendererInfo;


    public enum LightMapType
    {
        MainCity,
        World,
        Fight,
    }

    public LightMapType mType;
    public int LightmapIndexOffset = 0;
    public int LightmapCount
    {
        get
        {
            return m_Lightmaps.Length;
        }
    }

    private const string PathFar = "LightMap/{0}/Lightmap-{1}_comp_light";
    //private const string PathNear = "LightMap/{0}/Lightmap-{1}_comp_light";
    private const string MainCity = "MainCity";
    private const string World = "World";
    private const string Fight = "Fight";
    bool first = true;

    public void Apply(Dictionary<string, Texture2D> lmMap)
    {
        //if (first)
        //{
        //    first = false;
        //    string path1;
        //    if (mType == LightMapType.MainCity)
        //    {
        //        path1 = MainCity;
        //    }
        //    else if (mType == LightMapType.World)
        //    {
        //        path1 = World;
        //    }
        //    else
        //    {
        //        path1 = Fight;
        //    }

        //    for (int i = 0; i < m_Lightmaps.Length; i++)
        //    {
        //        Texture2D pic = Resources.Load(string.Format(PathFar, path1, i)) as Texture2D;
        //        if (pic != null)
        //        {
        //            m_Lightmaps[i].lightmapFar = pic;
        //        }
        //    }
        //}


        //if (m_RendererInfo == null || m_RendererInfo.Length == 0)
        //    return;

        //方式一
        // List<LightmapData> lightmapsLst = new List<LightmapData>();
        // lightmapsLst.AddRange(LightmapSettings.lightmaps);
        // var lightmaps = LightmapSettings.lightmaps;
        // var combinedLightmaps = new LightmapData[lightmaps.Length + m_Lightmaps.Length];

        // lightmaps.CopyTo(combinedLightmaps, 0);
        // for (int i = 0; i < m_Lightmaps.Length; i++)
        // {
        //     combinedLightmaps[i + lightmaps.Length] = new LightmapData();
        //     if (m_Lightmaps[i].lightmapFar != null)
        //     {
        //         combinedLightmaps[i + lightmaps.Length].lightmapFar = m_Lightmaps[i].lightmapFar;
        //     }
        //     if (m_Lightmaps[i].lightmapNear != null)
        //     {
        //         combinedLightmaps[i + lightmaps.Length].lightmapNear = m_Lightmaps[i].lightmapNear;
        //     }
        // }

        // ApplyRendererInfo(m_RendererInfo, LightmapIndexOffset);
        // ApplyTerrainRendererInfo(m_TerrainRendererInfo, LightmapIndexOffset);


        // // lightmapsLst.Sort(LightmapIndexOffset, m_Lightmaps.Length, new CompareLightmap(m_Lightmaps));

        // LightmapSettings.lightmaps = combinedLightmaps;

        //方式二
        // var combinedLightmaps = new LightmapData[m_Lightmaps.Length];
        // for (int i = 0; i < m_Lightmaps.Length; i++)
        // {
        //    combinedLightmaps[i] = new LightmapData();
        //    if (m_Lightmaps[i].lightmapFar != null)
        //    {
        //        combinedLightmaps[i].lightmapFar = m_Lightmaps[i].lightmapFar;
        //    }
        //    if (m_Lightmaps[i].lightmapNear != null)
        //    {
        //        combinedLightmaps[i].lightmapNear = m_Lightmaps[i].lightmapNear;
        //    }
        // }

        // ApplyRendererInfo(m_RendererInfo, LightmapIndexOffset);
        // ApplyTerrainRendererInfo(m_TerrainRendererInfo, LightmapIndexOffset);

        // LightmapSettings.lightmaps = combinedLightmaps;


        //方式三
        List<LightmapData> lightmapsLst = new List<LightmapData>();
        lightmapsLst.AddRange(LightmapSettings.lightmaps);
        var lightmaps = LightmapSettings.lightmaps;
        var combinedLightmaps = new LightmapData[lightmaps.Length + m_Lightmaps.Length];

        lightmaps.CopyTo(combinedLightmaps, 0);
        for (int i = 0; i < m_Lightmaps.Length; i++)
        {
            LightmapData data = new LightmapData();
            combinedLightmaps[i + lightmaps.Length] = data;
            data.lightmapFar = m_Lightmaps[i].lightmapFar;
            data.lightmapNear = m_Lightmaps[i].lightmapNear;
            // string farName = m_Lightmaps[i].FarName;
            // string nearName = m_Lightmaps[i].NearName;
            // if (string.IsNullOrEmpty(farName) == false)
            // {
            //     if (lmMap.ContainsKey(farName) == true)
            //     {
            //         data.lightmapFar = lmMap[farName];
            //     }
            // }

            // if (string.IsNullOrEmpty(nearName) == false)
            // {
            //     if (lmMap.ContainsKey(nearName) == true)
            //     {
            //         data.lightmapNear = lmMap[nearName];
            //     }
            // }
        }

        ApplyRendererInfo(m_RendererInfo, LightmapIndexOffset);
        ApplyTerrainRendererInfo(m_TerrainRendererInfo, LightmapIndexOffset);


        // lightmapsLst.Sort(LightmapIndexOffset, m_Lightmaps.Length, new CompareLightmap(m_Lightmaps));

        LightmapSettings.lightmaps = combinedLightmaps;
    }


    static void ApplyRendererInfo(RendererInfo[] infos, int lightmapOffsetIndex)
    {
        for (int i = 0; i < infos.Length; i++)
        {
            var info = infos[i];
            if (info.renderer != null)
            {
                info.renderer.lightmapIndex = info.lightmapIndex + lightmapOffsetIndex;
                info.renderer.lightmapScaleOffset = info.lightmapScaleOffset;
            }

        }
    }

    static void ApplyTerrainRendererInfo(TerrainRendererInfo[] infos, int lightmapOffsetIndex)
    {
        for (int i = 0; i < infos.Length; i++)
        {
            var info = infos[i];
            if (info.terrain != null)
            {
                info.terrain.lightmapIndex = info.lightmapIndex + lightmapOffsetIndex;
                info.terrain.lightmapScaleOffset = info.lightmapScaleOffset;
            }
        }
    }


#if UNITY_EDITOR
    [MenuItem("slg/手动应用光照图")]
    static void ManualApplyLightmap()
    {
        Transform[] trans = Selection.GetTransforms(SelectionMode.Unfiltered);
        for (int i = 0; i < trans.Length; i++)
        {
            PrefabLightmapData2 script = trans[i].GetComponent<PrefabLightmapData2>();
            ApplyRendererInfo(script.m_RendererInfo, script.LightmapIndexOffset);
            ApplyTerrainRendererInfo(script.m_TerrainRendererInfo, script.LightmapIndexOffset);
        }
    }

    [UnityEditor.MenuItem("Assets/Bake Prefab Lightmaps")]
    static void GenerateLightmapInfo()
    {
        if (UnityEditor.Lightmapping.giWorkflowMode != UnityEditor.Lightmapping.GIWorkflowMode.OnDemand)
        {
            Debug.LogError("ExtractLightmapData requires that you have baked you lightmaps and Auto mode is disabled.");
            return;
        }
        UnityEditor.Lightmapping.BakeAsync();
        Lightmapping.completed = OnCompleted;

    }

    static void OnCompleted()
    {
        PrefabLightmapData2[] prefabs = FindObjectsOfType<PrefabLightmapData2>();

        foreach (var instance in prefabs)
        {
            var gameObject = instance.gameObject;
            var rendererInfos = new List<RendererInfo>();
            var lightmaps = new List<LightmapInfo>();
            var terrainRendererInfo = new List<TerrainRendererInfo>();
            GenerateLightmapInfo(gameObject, rendererInfos, lightmaps, terrainRendererInfo);

            instance.m_RendererInfo = rendererInfos.ToArray();
            instance.m_Lightmaps = lightmaps.ToArray();
            instance.m_TerrainRendererInfo = terrainRendererInfo.ToArray();
            var targetPrefab = UnityEditor.PrefabUtility.GetPrefabParent(gameObject) as GameObject;
            if (targetPrefab != null)
            {
                //UnityEditor.Prefab
                UnityEditor.PrefabUtility.ReplacePrefab(gameObject, targetPrefab);
            }
        }
        //EditorUtility.ClearProgressBar();
    }

    static void GenerateLightmapInfo(GameObject root, List<RendererInfo> rendererInfos, List<LightmapInfo> lightmaps, List<TerrainRendererInfo> terrainRendererInfos)
    {
        var renderers = root.GetComponentsInChildren<MeshRenderer>();
        var terrains = root.GetComponentsInChildren<Terrain>();
        int i = 0;
        foreach (MeshRenderer renderer in renderers)
        {
            i++;
            EditorUtility.DisplayProgressBar("序列化网格光照信息", "正在序列化网格光照信息。。。。", 1f * i / renderers.Length);
            if (renderer.lightmapIndex != -1)
            {
                RendererInfo info = new RendererInfo();
                info.renderer = renderer;
                info.lightmapScaleOffset = renderer.lightmapScaleOffset;
                //info.lightmapIndex = renderer.lightmapIndex;
                Texture2D lightmapFar = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapFar;
                Texture2D lightmapNear = LightmapSettings.lightmaps[renderer.lightmapIndex].lightmapNear;
                LightmapInfo light = new LightmapInfo();
                light.lightmapFar = lightmapFar;
                light.lightmapNear = lightmapNear;

                info.lightmapIndex = lightmaps.IndexOf(light);
                if (info.lightmapIndex == -1)
                {
                    info.lightmapIndex = lightmaps.Count;
                    lightmaps.Add(light);
                }

                rendererInfos.Add(info);
            }
        }
        EditorUtility.ClearProgressBar();

        int j = 0;
        foreach (var terrain in terrains)
        {
            j++;
            EditorUtility.DisplayProgressBar("序列化地形光照信息", "正在序列化地形光照信息。。。。", 1f * i / terrains.Length);
            if (terrain.lightmapIndex != -1)
            {
                TerrainRendererInfo info = new TerrainRendererInfo();
                info.terrain = terrain;
                info.lightmapScaleOffset = terrain.lightmapScaleOffset;

                Texture2D lightmapFar = LightmapSettings.lightmaps[terrain.lightmapIndex].lightmapFar;
                Texture2D lightmapNear = LightmapSettings.lightmaps[terrain.lightmapIndex].lightmapNear;
                LightmapInfo light = new LightmapInfo();
                light.lightmapFar = lightmapFar;
                light.lightmapNear = lightmapNear;

                info.lightmapIndex = lightmaps.IndexOf(light);
                if (info.lightmapIndex == -1)
                {
                    info.lightmapIndex = lightmaps.Count;
                    lightmaps.Add(light);
                }

                terrainRendererInfos.Add(info);
            }
        }
        EditorUtility.ClearProgressBar();
        //if(terrains != null && terrains.lightmapIndex != -1)
        //{
        //    terrainRendererInfos.terrain = terrains;
        //    terrainRendererInfos.lightmapOffsetScale = terrains.lightmapScaleOffset;
        //    terrainRendererInfos.lightmapIndex = terrains.lightmapIndex;
        //    Texture2D lightmapFar2 = LightmapSettings.lightmaps[terrains.lightmapIndex].lightmapFar;
        //    Texture2D lightmapNear2 = LightmapSettings.lightmaps[terrains.lightmapIndex].lightmapNear;
        //    LightmapInfo light = new LightmapInfo();
        //    light.lightmapFar = lightmapFar2;
        //    light.lightmapNear = lightmapNear2;

        //    terrainRendererInfos.lightmapIndex = lightmaps.IndexOf(light);
        //    if (terrainRendererInfos.lightmapIndex == -1)
        //    {
        //        terrainRendererInfos.lightmapIndex = lightmaps.Count;
        //        lightmaps.Add(light);
        //    }
        //}


    }
#endif

    class CompareLightmap : IComparer<LightmapData>
    {
        LightmapInfo[] mArr;
        public CompareLightmap(LightmapInfo[] arr)
        {
            mArr = arr;
        }
        public int Compare(LightmapData x, LightmapData y)
        {
            int xIndex = GetIndex(x);
            int yIndex = GetIndex(y);

            return xIndex.CompareTo(yIndex);
        }

        private int GetIndex(LightmapData x)
        {
            for (int i = 0; i < mArr.Length; i++)
            {
                if (mArr[i].lightmapFar.name == x.lightmapFar.name)
                {
                    return i;
                }
            }

            return -1;
        }
    }
}